home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-02-26 | 28.5 KB | 1,149 lines |
- Newsgroups: comp.sources.misc
- subject: v10i082: Stat(1)
- From: dds@cc.ic.ac.uk (Diomidis Spinellis)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 10, Issue 82
- Submitted-by: dds@cc.ic.ac.uk (Diomidis Spinellis)
- Archive-name: stat
-
- Stat is a program that brings all the power of the stat(2) system call
- to the shell programer. It can be used to print various
- characteristics of a file such as its size, permissions, dates, type
- etc. in a variety of user specified formats. The output can be easily
- manipulated with tools such as awk, sed and sort to provide complex
- file selection and printing mechanisms. Obvious applications are
- novice-user-friendly versions of ls(1) and getting the mode of a file
- in a way that can be later used by chmod(1). It has been tested under
- 4.3 BSD, AIX, HP/UX, SunOS, and Ultrix.
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # Makefile
- # stat.1
- # stat.c
- # This archive created: Wed Feb 21 21:21:02 1990
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(1374 characters)'
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- sed 's/^X//' << \SHAR_EOF > 'README'
- X
- XStat is a program that brings all the power of the stat(2) system call
- Xto the shell programer. It can be used to print various
- Xcharacteristics of a file such as its size, permissions, dates, type
- Xetc. in a variety of user specified formats. The output can be easily
- Xmanipulated with tools such as awk, sed and sort to provide complex
- Xfile selection and printing mechanisms. Obvious applications are
- Xnovice-user-friendly versions of ls(1) and getting the mode of a file
- Xin a way that can be later used by chmod(1). It has been tested under
- X4.3 BSD, AIX, HP/UX, SunOS, and Ultrix.
- X
- XThe output format is specified at three different levels in a
- Xprintf(3S) like way. A global output format string specifies the
- Xitems which are printed. The way the different time values are printed
- Xis specified by other format strings. Finaly the way each individual
- Xfield is printed (number base, justification, padding) can be specified
- Xusing the normal printf specifications.
- X
- XComments and additions can be sent to the author:
- X
- X Diomidis Spinellis
- X Myrsinis 1
- X GR-145 62 Kifissia
- X GREECE
- X
- X--
- XDiomidis Spinellis Internet: dds@cc.ic.ac.uk
- XDepartment of Computing UUCP: ...!ukc!iccc!dds
- XImperial College JANET: dds@uk.ac.ic.cc
- XLondon SW7 2BZ #include "/dev/tty"
- SHAR_EOF
- if test 1374 -ne "`wc -c < 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 1374 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Makefile'" '(464 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- sed 's/^X//' << \SHAR_EOF > 'Makefile'
- X#
- X# Makefile for stat
- X#
- X
- X# Binary destination
- Xbin = /usr/local/bin
- X
- X# Unformated manual page destination
- Xmansrc = /usr/local/man/man1
- X
- XCC = cc
- XCFLAGS = -O
- XLINTFLAGS = -chabx
- X
- Xall: stat
- X
- Xstat: stat.c
- X $(CC) $(CFLAGS) stat.c -o stat
- X
- Xinstall: stat stat.1
- X install stat $(bin)
- X install stat.1 $(mansrc)
- X
- Xclean:
- X rm -f stat.o
- X
- Xclobber:
- X rm -f stat.o stat core
- X
- Xlint:
- X lint $(LINTFLAGS) stat.c >stat.lint
- X
- Xshar:
- X shar -cv -p X README Makefile stat.1 stat.c >stat.shar
- SHAR_EOF
- if test 464 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 464 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'stat.1'" '(8549 characters)'
- if test -f 'stat.1'
- then
- echo shar: will not over-write existing file "'stat.1'"
- else
- sed 's/^X//' << \SHAR_EOF > 'stat.1'
- X.\"
- X.\" (C) Copyright 1989 Diomidis D. Spinellis. All rights reserved.
- X.\"
- X.\" Redistribution and use in source and formated forms are permitted
- X.\" provided that the above copyright notice and this paragraph are
- X.\" duplicated in all such forms and that any documentation,
- X.\" advertising materials, and other materials related to such
- X.\" distribution and use acknowledge that the software was developed
- X.\" by Diomidis D. Spinellis.
- X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X.\"
- X.TH STAT 1
- X.SH NAME
- Xstat \- print file status information
- X.SH SYNOPSIS
- X.B stat
- X[
- X.BI \-g
- X]
- X[
- X.BI \-l
- X]
- X[
- X.BI \-e
- X]
- X[
- X.BI \-f " format"
- X]
- X[
- X.BI \-t " time_format"
- X]
- X[
- X.BI \-m " time_format"
- X]
- X[
- X.BI \-a " time_format"
- X]
- X[
- X.BI \-c " time_format"
- X]
- X[
- X.BI \-q " mode_names"
- X]
- X[
- X.BI \-y " type_names"
- X]
- Xfile ...
- X.SH DESCRIPTION
- X.I Stat
- Xprints status information for each of the files specified. If a
- Xfile name is `\-', then status information about the standard input
- Xis displayed.
- X.PP
- XThe output can be specified by means of
- X.I printf
- Xlike format specifications. If no format specifications are given, then
- X.I ``ls -l''
- Xlike output is produced.
- X.SH OPTIONS
- X.TP
- X.B \-g
- XList time fields in UTC (GMT) instead of local time.
- X.TP
- X.B \-l
- XFor symbolic links list the status of the the file it points to instead of
- Xthe status of the link (i.e. follow symbolic links).
- X.TP
- X.B \-e
- XExit immediately with an error when stat can not be performed on a file. If
- Xthis
- Xflag is not given then error messages are printed, but the program continues
- Xto go through the list of files.
- X.TP
- X.BI \-f " output format"
- XSpecify the output format.
- X.TP
- X.BI \-a " time format"
- XSpecify the output format for the file access time field.
- X.TP
- X.BI \-m " time format"
- XSpecify the output format for the file modification time field.
- X.TP
- X.BI \-c " time format"
- XSpecify the output format for the file status change time field.
- X.TP
- X.BI \-t " time format"
- XSpecify the output format for the current time field.
- X.TP
- X.BI \-q " mode names"
- XSpecify the English description of the file mode giving a list of 24 strings.
- XThe strings are separated by an arbitrary character and the list should start
- Xand end with that character.
- XThe first three strings
- Xdescribe the set user id, set group id and sticky modes.
- XAfter that, nine strings, the descriptions for read
- Xpermission, write permission and execute permission, first for the owner,
- Xthen for the group and then for others must be given.
- XAnother set
- Xof 12 strings must follow describing the semantics of the above in
- Xthe case of directories.
- X.TP
- X.BI \-y " type names"
- XSpecify the English description of the file type giving a list of seven strings.
- XThe list is given as in the
- X.I -q
- Xoption and the strings are the descriptions to be used for directories,
- Xblock special files, character special files, symbolic links, named pipes,
- Xsockets and regular files. All types must be given, even if not supported
- Xon a system.
- X.PP
- XFive format specifications can be given: one for
- Xthe whole output and four for the output format of different time values.
- XThe format specification
- Xis a string. All characters in the format specification are printed except
- Xfor characters following a `%' sign. If the first character after a `%' sign
- Xis an open bracket `(' then the characters up to the matching closing bracket
- Xare taken as a
- X.I printf
- Xformat specification that will be used to print the item specified.
- XA `%' sign in the printf format specification is not needed.
- XNote that some systems may not support some of the options.
- X.PP
- XCharacters following a `%' sign are
- Xconverted in the global output specification as follows:
- X.RS
- X.PD 0
- X.TP 5
- X.B v
- Xdevice the file resides on in decimal
- X.TP 5
- X.B i
- Xthe file's inode number in decimal
- X.TP 5
- X.B p
- Xthe file's protection in octal
- X.TP 5
- X.B P
- Xthe file's protection in an
- X.I ls -l
- Xlike fashion
- X.TP 5
- X.B q
- Xthe file's protection as a series of nine 0 or 1 digits. The default format
- Xspecification for printf is `%s' and applies to each individual digit
- X.TP 5
- X.B Q
- Xthe file's protection using an English description. The description can be
- Xoptionaly specified using the
- X.I .q
- Xoption. If the file is a symbolic link and the
- X.I -l
- Xoption has not been given, nothing is printed
- X.TP 5
- X.B l
- Xthe number of links the file has in decimal
- X.TP 5
- X.B u
- Xthe user id of the owner of the file in decimal
- X.TP 5
- X.B U
- Xthe user id of the owner of the file as a string
- X.TP 5
- X.B g
- Xthe group id of the owner of the file in decimal
- X.TP 5
- X.B G
- Xthe group id of the owner of the file as a string
- X.TP 5
- X.B r
- Xthe device identifier (only for special files)
- X.TP 5
- X.B s
- Xtotal byte size of the file in decimal
- X.TP 5
- X.B a
- Xlast access time of file in seconds since 1970
- X.TP 5
- X.B m
- Xlast modification time of file in seconds since 1970
- X.TP 5
- X.B c
- Xlast status change time of file in seconds since 1970
- X.TP 5
- X.B t
- Xcurrent time in seconds since 1970
- X.TP 5
- X.B A
- Xlast access time of file as the string specified by the access time format
- X.TP 5
- X.B M
- Xlast modification time of file as the string specified by the modification time
- Xformat
- X.TP 5
- X.B C
- Xlast status change time of file as the string specified by the change
- Xtime format
- X.TP 5
- X.B T
- Xcurrent time as the string specified by the current time format
- X.TP 5
- X.B z
- Xpreferred blocksize for file I/O
- X.TP 5
- X.B b
- Xactual number of blocks allocated
- X.TP 5
- X.B n
- Xthe name of the file
- X.TP 5
- X.B f
- Xa `/' for directories, `@' for symbolic links, `=' for AF_UNIX domain sockets
- Xand `*' for executable files. If the name of a symbolic link or an arrow is
- Xprinted as a result of %L or %- then the `@' is not printed.
- X.TP 5
- X.B F
- XThe type of the file is printed as one of the symbols S_IFIDR, S_IFBLK,
- XS_IFCHAR, S_IFLNK, S_IFIFO, S_IFSOCK, S_IFREG for directories, block
- Xspecial files, character special files, symbolic links, FIFO special files,
- XAF_UNIX domain sockets and regular files.
- X.TP 5
- X.B Y
- XThe type of the file using an English description, optionaly specified using
- Xthe
- X.I -y
- Xoption
- X.TP 5
- X.B L
- Xif the file is a symbolic link, the contents of the link
- X.TP 5
- X.B -
- Xif the file is a symbolic link, the character sequence ` -> '
- X.PD
- X.RE
- X.PP
- XThe default time format specification produces
- X.I `ls -l'
- Xlike time output.
- XCharacters following a `%' sign are
- Xconverted in the time output specification as follows:
- X.RS
- X.PD 0
- X.TP 5
- X.B m
- Xthe month number in decimal (1-12)
- X.TP 5
- X.B d
- Xthe day of month number in decimal (1-31)
- X.TP 5
- X.B y
- Xthe year in decimal (1900-...)
- X.TP 5
- X.B Y
- Xthe year in decimal printed only if the time is more that half a year older
- Xthan the current time.
- X.TP 5
- X.B H
- Xthe hour of the day in decimal (0-23)
- X.TP 5
- X.B M
- Xminutes in decimal (0-59)
- X.TP 5
- X.B S
- Xseconds in decimal (0-59)
- X.TP 5
- X.B T
- Xhours and minutes as 00:00 printed only if time is less than half a
- Xyear older than the current time. (A note for pedants: If the time
- Xis exactly equal to the current time minus half a year than hours and
- Xminutes are printed.)
- X.TP 5
- X.B j
- Xthe day of the year in decimal (0-365)
- X.TP 5
- X.B w
- Xthe day of the week in decimal (Sunday is 0)
- X.TP 5
- X.B a
- Xthe three letter abbreviation of the day of the week
- X.TP 5
- X.B h
- Xthe three letter abbreviation of the month
- X.TP 5
- X.B z
- Xthe offset of the time from UTC (GMT) in seconds
- X.TP 5
- X.B Z
- Xabbreviation of the timezone name
- X.TP 5
- X.B D
- Xthe letters DST if daylight savings time is in effect
- X.TP 5
- X.B t
- XThe time in the form mmddhhmmyy. This form can be used as an argument
- Xof the System V touch command.
- X.PD
- X.RE
- X.PP
- X.SH EXAMPLES
- X.PP
- XList all files in a directory in a
- X.I `ls -F'
- Xlike fashion (the default time format is `%h %(2d)d %T%(5d)Y'):
- X.nf
- X stat -f '%P%(3d)l %(-8s)U %(8ld)s %M %n%-%L%F' *
- X.fi
- X.PP
- XMake depend in a makefile without modifying the permissions of Makefile
- X(Makefile can be read only from a version control system).
- X.nf
- X PERMS=`stat -f %p Makefile` ;\\
- X chmod 600 Makefile ;\\
- X mkdep $(FILES) ;\\
- X chmod $$PERMS Makefile
- X.fi
- X.PP
- XAn extremely verbose version of ls:
- X.nf
- X#!/bin/sh
- XT='%a %d %h %y %H:%M:%S'
- Xstat -a "$T" -c "$T" -m "$T" -f '
- XFile: %n
- XType: %Y
- XDevice: %v(0x%(x)v)
- XInode: %i(0x%(x)i)
- XPotection: %Q
- XUser: %U(%u)
- XGroup: %G(%g)
- XFile size: %s byte(s) %b block(s)
- XLast access: %A
- XLast change: %M
- XStatus change: %C
- X ' -y '
- XDirectory
- XBlock device
- XCharacter device
- XSymbolic link
- XNamed pipe
- XSocket
- XNormal file
- X ' $*
- X.fi
- X
- X.SH AUTHOR
- X(C) Copyright 1989 Diomidis D. Spinellis (dds@cc.ic.ac.uk). All rights reserved.
- X.SH SEE ALSO
- Xls(1), find(1), printf(3S)
- X.SH BUGS
- X.PP
- XNot quite as many options as ls.
- SHAR_EOF
- if test 8549 -ne "`wc -c < 'stat.1'`"
- then
- echo shar: error transmitting "'stat.1'" '(should have been 8549 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'stat.c'" '(14832 characters)'
- if test -f 'stat.c'
- then
- echo shar: will not over-write existing file "'stat.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'stat.c'
- X/*
- X * stat - List the status information of a list of files
- X *
- X * (C) Copyright 1989 Diomidis D. Spinellis. All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by Diomidis D. Spinellis.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * $Header: stat.c,v 1.9 89/11/03 22:53:12 dds Rel $
- X *
- X */
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <varargs.h>
- X#include <pwd.h>
- X#include <grp.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/time.h>
- X#include <sys/param.h>
- X
- X#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
- X
- X#ifndef lint
- Xstatic char RCSid[] = "$Header: stat.c,v 1.9 89/11/03 22:53:12 dds Rel $";
- X#endif
- X
- Xint debug = 0;
- Xint lflag = 0; /* Follow links */
- Xint gflag = 0; /* Use GMT */
- Xint eflag = 0; /* Exit on error */
- Xchar *progname; /* Base name of the program */
- X/* Output format string */
- Xchar *format = "%P%(3d)l %(-8s)U %(8ld)s %M %n%-%L";
- Xchar *ttformat = "%h %(2d)d %T%(5d)Y"; /* Current time format */
- Xchar *tcformat = "%h %(2d)d %T%(5d)Y"; /* Creation time format */
- Xchar *taformat = "%h %(2d)d %T%(5d)Y"; /* Access time format */
- Xchar *tmformat = "%h %(2d)d %T%(5d)Y"; /* Modification time format */
- Xchar *typename[]; /* File type english names */
- Xchar *modename[]; /* File mode english names */
- Xstruct tm currtime; /* Current time structure */
- Xlong currclock, halfyearago; /* ... in seconds */
- X
- Xextern void error(), exit();
- Xextern struct tm *localtime(), *gmtime();
- X
- Xstatic void parsenames();
- X
- X/*
- X * main - parse arguments and handle options
- X */
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int c;
- X int errflg = 0;
- X extern int optind;
- X extern char *optarg;
- X extern char *mkprogname();
- X void process();
- X struct timeval time;
- X struct timezone zone;
- X
- X progname = mkprogname(argv[0]);
- X
- X while ((c = getopt(argc, argv, "dglf:t:a:m:c:q:y:")) != EOF)
- X switch (c) {
- X#ifndef NDEBUG
- X case 'd': /* Debugging. */
- X debug++;
- X break;
- X#endif
- X case 'e':
- X eflag++;
- X break;
- X case 'g':
- X gflag++;
- X break;
- X case 'l':
- X lflag++;
- X break;
- X case 'c': /* Format for current time specification */
- X tcformat = optarg;
- X break;
- X case 'a': /* Format for current time specification */
- X taformat = optarg;
- X break;
- X case 'm': /* Format for current time specification */
- X tmformat = optarg;
- X break;
- X case 't': /* Format for current time specification */
- X ttformat = optarg;
- X break;
- X case 'f': /* Format specification */
- X format = optarg;
- X break;
- X case 'q': /* Names for english file mode descriptions */
- X parsenames(optarg, modename, 24, "mode");
- X break;
- X case 'y': /* Names for file type descriptions */
- X parsenames(optarg, typename, 7, "type");
- X break;
- X case '?':
- X default:
- X errflg++;
- X break;
- X }
- X if (errflg || optind >= argc) {
- X fprintf(stderr, "usage: %s [-f format] [-t date_format]file ...\n", progname);
- X exit(2);
- X }
- X
- X gettimeofday(&time, &zone);
- X currclock = time.tv_sec;
- X halfyearago = currclock - 365L * 24L * 60L * 60L / 2L;
- X if (gflag)
- X currtime = *gmtime(&time.tv_sec);
- X else
- X currtime = *localtime(&time.tv_sec);
- X for (; optind < argc; optind++)
- X process(argv[optind]);
- X exit(0);
- X}
- X
- X/*
- X * List the mode of a file a la ls
- X */
- X#ifdef __GCC__
- Xinline
- X#endif
- Xstatic void
- Xlsmode(mode)
- X unsigned short mode;
- X{
- X if ((mode & S_IFMT) == S_IFDIR)
- X putchar('d');
- X else if ((mode & S_IFMT) == S_IFBLK)
- X putchar('b');
- X else if ((mode & S_IFMT) == S_IFCHR)
- X putchar('c');
- X#ifdef S_IFLNK
- X else if ((mode & S_IFMT) == S_IFLNK)
- X putchar('l');
- X#endif
- X#ifdef S_IFIFO
- X else if ((mode & S_IFMT) == S_IFIFO)
- X putchar('p');
- X#endif
- X#ifdef S_IFSOCK
- X else if ((mode & S_IFMT) == S_IFSOCK)
- X putchar('s');
- X#endif
- X else
- X putchar('-');
- X putchar((mode & (S_IREAD >> 0)) ? 'r' : '-');
- X putchar((mode & (S_IWRITE >> 0)) ? 'w' : '-');
- X if (mode & S_ISUID)
- X putchar((mode & (S_IEXEC >> 0)) ? 's' : 'S');
- X else
- X putchar((mode & (S_IEXEC >> 0)) ? 'x' : '-');
- X putchar((mode & (S_IREAD >> 3)) ? 'r' : '-');
- X putchar((mode & (S_IWRITE >> 3)) ? 'w' : '-');
- X if (mode & S_ISGID)
- X putchar((mode & (S_IEXEC >> 3)) ? 's' : 'S');
- X else
- X putchar((mode & (S_IEXEC >> 3)) ? 'x' : '-');
- X putchar((mode & (S_IREAD >> 6)) ? 'r' : '-');
- X putchar((mode & (S_IWRITE >> 6)) ? 'w' : '-');
- X if (mode & S_ISVTX)
- X putchar((mode & (S_IEXEC >> 3)) ? 't' : 'T');
- X else
- X putchar((mode & (S_IEXEC >> 3)) ? 'x' : '-');
- X}
- X
- X#define optform(x) (form[1]?form:(x))
- Xstatic char form[512] = "%";
- X
- X/*
- X * Print time using the time format
- X */
- Xstatic
- Xtimef(clock, format)
- X long clock;
- X char *format;
- X{
- X struct tm *t;
- X char c, *p, *fp;
- X static char *weekday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- X static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- X
- X if (gflag)
- X t = gmtime(&clock);
- X else
- X t = localtime(&clock);
- X for (p = format; *p; p++) {
- X c = *p;
- X if (c != '%')
- X putchar(c);
- X else {
- X fp = form + 1;
- X p++;
- X if (*p == '(') {
- X p++;
- X while (*p && *p != ')')
- X *fp++ = *p++;
- X if (*p)
- X p++;
- X }
- X *fp = 0;
- X switch (*p) {
- X case 'm':
- X printf(optform("%d"), t->tm_mon + 1);
- X break;
- X case 'd':
- X printf(optform("%d"), t->tm_mday);
- X break;
- X case 'y':
- X printf(optform("%d"), t->tm_year+1900);
- X break;
- X case 'Y':
- X if (clock < halfyearago)
- X printf(optform("%d"), t->tm_year+1900);
- X break;
- X case 'H':
- X printf(optform("%d"), t->tm_hour);
- X break;
- X case 'M':
- X printf(optform("%d"), t->tm_min);
- X break;
- X case 'T':
- X if (clock >= halfyearago)
- X printf("%02d:%02d", t->tm_hour, t->tm_min);
- X break;
- X case 'S':
- X printf(optform("%d"), t->tm_sec);
- X break;
- X case 'j':
- X printf(optform("%d"), t->tm_yday);
- X break;
- X case 'w':
- X printf(optform("%d"), t->tm_wday);
- X break;
- X case 'a':
- X printf(optform("%s"), weekday[t->tm_wday]);
- X break;
- X case 'h':
- X printf(optform("%s"), month[t->tm_mon]);
- X break;
- X#ifdef sun
- X case 'z':
- X printf(optform("%s"), t->tm_gmtoff);
- X break;
- X case 'Z':
- X printf(optform("%s"), t->tm_zone);
- X break;
- X#endif
- X case 'D':
- X printf(optform("%s"), t->tm_isdst ? "DST" : "");
- X break;
- X case 't':
- X printf("%02d%02d%02d%02d%02d", t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_year);
- X break;
- X default :
- X putchar(*p);
- X break;
- X }
- X }
- X }
- X}
- X
- X/*
- X * process - process input file
- X */
- Xstatic void
- Xprocess(inname)
- X char *inname;
- X{
- X struct stat statbuf;
- X struct group *grp, *getgrgid();
- X struct passwd *pwd, *getpwuid();
- X int uid = -10, gid = -10; /* Cached */
- X char *pw_name, *gr_name;
- X char *p, c, *fp, *ctime();
- X int i, j;
- X int Lprinted = 0;
- X
- X if (STREQ(inname, "-")) {
- X if (fstat(0, &statbuf) < 0) {
- X error("can't fstat `%s'", inname);
- X return;
- X }
- X } else {
- X if (lflag) {
- X if (stat(inname, &statbuf) < 0) {
- X error("can't stat `%s'", inname);
- X return;
- X }
- X } else {
- X if (lstat(inname, &statbuf) < 0) {
- X error("can't lstat `%s'", inname);
- X return;
- X }
- X }
- X }
- X
- X for (p = format; *p; p++) {
- X c = *p;
- X if (c != '%')
- X putchar(c);
- X else {
- X fp = form + 1;
- X p++;
- X if (*p == '(') {
- X p++;
- X while (*p && *p != ')')
- X *fp++ = *p++;
- X if (*p)
- X p++;
- X }
- X *fp = 0;
- X switch (*p) {
- X case 'v':
- X printf(optform("%d"), statbuf.st_dev);
- X break;
- X case 'i':
- X printf(optform("%lu"), statbuf.st_ino);
- X break;
- X case 'p':
- X printf(optform("%o"), statbuf.st_mode);
- X break;
- X case 'P':
- X lsmode(statbuf.st_mode);
- X break;
- X case 'l':
- X printf(optform("%d"), statbuf.st_nlink);
- X break;
- X case 'u':
- X printf(optform("%d"), statbuf.st_uid);
- X break;
- X case 'g':
- X printf(optform("%d"), statbuf.st_gid);
- X break;
- X case 'U':
- X if (uid != statbuf.st_uid) {
- X if (pwd = getpwuid(statbuf.st_uid))
- X pw_name = pwd->pw_name;
- X else
- X pw_name = "[UNKOWN]";
- X }
- X printf(optform("%s"), pw_name);
- X break;
- X case 'G':
- X if (gid != statbuf.st_gid) {
- X if (grp = getgrgid(statbuf.st_gid))
- X gr_name = grp->gr_name;
- X else
- X gr_name = "[UNKOWN]";
- X }
- X printf(optform("%s"), gr_name);
- X break;
- X case 'r':
- X printf(optform("%d"), statbuf.st_rdev);
- X break;
- X case 's':
- X printf(optform("%ld"), statbuf.st_size);
- X break;
- X case 'a':
- X printf(optform("%ld"), statbuf.st_atime);
- X break;
- X case 'm':
- X printf(optform("%ld"), statbuf.st_mtime);
- X break;
- X case 'c':
- X printf(optform("%ld"), statbuf.st_ctime);
- X break;
- X case 't':
- X printf(optform("%ld"), currclock);
- X break;
- X case 'A':
- X timef(statbuf.st_atime, taformat);
- X break;
- X case 'M':
- X timef(statbuf.st_mtime, tmformat);
- X break;
- X case 'C':
- X timef(statbuf.st_ctime, tcformat);
- X break;
- X case 'T':
- X timef(currclock, ttformat);
- X break;
- X#ifndef AIX
- X case 'z':
- X printf(optform("%ld"), statbuf.st_blksize);
- X break;
- X case 'b':
- X printf(optform("%ld"), statbuf.st_blocks);
- X break;
- X#endif
- X case 'n':
- X printf(optform("%s"), inname);
- X break;
- X case 'f':
- X#ifdef S_IFLNK
- X if ((statbuf.st_mode & S_IFMT) == S_IFLNK && Lprinted)
- X break;
- X#endif
- X if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
- X putchar('/');
- X#ifdef S_IFLNK
- X else if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
- X putchar('@');
- X#endif
- X#ifdef S_IFSOCK
- X else if ((statbuf.st_mode & S_IFMT) == S_IFSOCK)
- X putchar('=');
- X#endif
- X else if (statbuf.st_mode & (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6)))
- X putchar('*');
- X else
- X putchar(' ');
- X break;
- X case 'F':
- X if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
- X printf(optform("%s"), "S_IFDIR");
- X else if ((statbuf.st_mode & S_IFMT) == S_IFBLK)
- X printf(optform("%s"), "S_IFBLK");
- X else if ((statbuf.st_mode & S_IFMT) == S_IFCHR)
- X printf(optform("%s"), "S_IFCHR");
- X#ifdef S_IFLNK
- X else if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
- X printf(optform("%s"), "S_IFLNK");
- X#endif
- X#ifdef S_IFIFO
- X else if ((statbuf.st_mode & S_IFMT) == S_IFIFO)
- X printf(optform("%s"), "S_IFIFO");
- X#endif
- X#ifdef S_IFSOCK
- X else if ((statbuf.st_mode & S_IFMT) == S_IFSOCK)
- X printf(optform("%s"), "S_IFSOCK");
- X#endif
- X else if ((statbuf.st_mode & S_IFMT) == S_IFREG)
- X printf(optform("%s"), "S_IFREG");
- X else
- X printf(optform("%s"), "");
- X break;
- X case 'Y':
- X if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
- X printf(optform("%s"), typename[0]);
- X else if ((statbuf.st_mode & S_IFMT) == S_IFBLK)
- X printf(optform("%s"), typename[1]);
- X else if ((statbuf.st_mode & S_IFMT) == S_IFCHR)
- X printf(optform("%s"), typename[2]);
- X#ifdef S_IFLNK
- X else if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
- X printf(optform("%s"), typename[3]);
- X#endif
- X#ifdef S_IFIFO
- X else if ((statbuf.st_mode & S_IFMT) == S_IFIFO)
- X printf(optform("%s"), typename[4]);
- X#endif
- X#ifdef S_IFSOCK
- X else if ((statbuf.st_mode & S_IFMT) == S_IFSOCK)
- X printf(optform("%s"), typename[5]);
- X#endif
- X else if ((statbuf.st_mode & S_IFMT) == S_IFREG)
- X printf(optform("%s"), typename[6]);
- X else
- X printf(optform("%s"), "");
- X break;
- X case 'q':
- X for (i = 0400; i; i >>= 1)
- X if (statbuf.st_mode & i)
- X printf(optform("%s"), "1");
- X else
- X printf(optform("%s"), "0");
- X break;
- X case 'Q':
- X#ifdef S_IFLNK
- X if ((statbuf.st_mode & S_IFMT) == S_IFLNK && ! lflag)
- X break;
- X#endif
- X if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
- X j = 12;
- X else
- X j = 0;
- X for (i = 04000; i; i >>= 1, j++)
- X if (statbuf.st_mode & i)
- X printf(optform("%s"), modename[j]);
- X break;
- X#ifdef S_IFLNK
- X case 'L':
- X if ((statbuf.st_mode & S_IFMT) == S_IFLNK) {
- X int len;
- X char buf[MAXPATHLEN];
- X
- X if ((len = readlink(inname, buf, MAXPATHLEN)) == -1) {
- X error("can't readlink `%s'", inname);
- X break;
- X }
- X buf[len] = 0;
- X printf(optform("%s"), buf);
- X Lprinted = 1;
- X } else
- X printf(optform("%s"), "");
- X break;
- X case '-':
- X if ((statbuf.st_mode & S_IFMT) == S_IFLNK) {
- X fputs(" -> ", stdout);
- X Lprinted = 1;
- X }
- X break;
- X#endif
- X default :
- X putchar(c);
- X break;
- X }
- X }
- X }
- X putchar('\n');
- X}
- X
- X/*
- X * error - report trouble
- X */
- Xstatic void /* does not return */
- Xerror(s1, s2)
- X char *s1, *s2;
- X{
- X extern int sys_nerr, errno;
- X extern char *sys_errlist[];
- X
- X fprintf(stderr, "%s: ", progname);
- X fprintf(stderr, s1, s2);
- X if( errno && errno <= sys_nerr )
- X fprintf(stderr, " (%s)", sys_errlist[errno]);
- X putc('\n', stderr);
- X if (eflag)
- X exit(1);
- X}
- X
- X/*
- X * mkprogname - convert string to a meaningful program name
- X * May change the string
- X */
- Xchar *
- Xmkprogname(s)
- X char *s;
- X{
- X char *p, *p2;
- X char *unkown="[unkown]";
- X
- X if (!s || !*s)
- X return unkown;
- X p = s;
- X if ((p2 = strrchr(s, '/')) > p) /* Check for path */
- X p = p2+1;
- X#ifdef MSDOS
- X if ((p2 = strrchr(s, '\\')) > p) /* Check for backslash path */
- X p = p2+1;
- X if ((p2 = strrchr(s, ':')) > p) /* Check for drive spec */
- X p = p2+1;
- X if ((p2 = strrchr(s, '.')) > p) /* Check for extension */
- X *p2=0;
- X for (p2=p; *p2; p2++) /* Make it lowercase */
- X if (isascii(*p2) && isupper(*p2))
- X *p2 = tolower(*p2);
- X#endif
- X if (*p)
- X return p;
- X else
- X return unkown;
- X}
- X
- Xchar *modename[] = { /* File mode english names */
- X "run with id of the owner ",
- X "run with id of the group ",
- X "stay in swap space on termination ",
- X "owner can read ",
- X "owner can change ",
- X "owner can execute ",
- X "group can read ",
- X "group can change ",
- X "group can execute ",
- X "anyone can read ",
- X "anyone can change ",
- X "anyone can execute ",
- X "",
- X "files inherit group ",
- X "only owners can delete files ",
- X "owner can read ",
- X "owner can change ",
- X "owner can access ",
- X "group can read ",
- X "group can change ",
- X "group can access ",
- X "anyone can read ",
- X "anyone can change ",
- X "anyone can access ",
- X};
- X
- X/* File type english names */
- Xchar *typename[] = {
- X "Directory",
- X "Block special",
- X "Character special",
- X "Symbolic link",
- X "Named pipe",
- X "Socket",
- X "Regular file",
- X};
- X
- X/*
- X * Convert a separator terminated list of strings starting with the
- X * terminator to an array. The strings should be exactly number else
- X * an error is printed.
- X */
- Xstatic void
- Xparsenames(names, array, number, errname)
- X char *names, *errname;
- X char *array[];
- X int number;
- X{
- X char term = *names;
- X char *p, *p2;
- X int count = 0;
- X
- X for (p = p2 = names + 1; *p ; p++)
- X if (*p == term) {
- X array[count++] = p2;
- X *p++ = 0;
- X p2 = p;
- X if (count > number)
- X break;
- X }
- X if (count != number) {
- X fprintf(stderr, "%s: expected %d arguments to specify file %s, got %d\n", progname, number, errname, count);
- X exit(1);
- X }
- X}
- SHAR_EOF
- if test 14832 -ne "`wc -c < 'stat.c'`"
- then
- echo shar: error transmitting "'stat.c'" '(should have been 14832 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
- --
- Diomidis Spinellis Internet: dds@cc.ic.ac.uk
- Department of Computing UUCP: ...!ukc!iccc!dds
- Imperial College JANET: dds@uk.ac.ic.cc
- London SW7 2BZ #include "/dev/tty"
-